/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "serial_impl.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_box
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static serial_impl::ITEM_DATA xos_item_data;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    serial_impl::serial_impl()
    {
    }

    serial_impl::~serial_impl()
    {
    }

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // char *
    // 

    int serial_impl::un_pack_str_array( const char * lpszData, int * lpnPos, int * lpnLen, int nBufSize, char * lppszStr, int nStrNum, int * lpnStrNum, int * lpnStrNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nStrNum ) )
        {
            ret = 1;
        }
        
        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            lppszStr += i * nBufSize;
            ret = un_pack_str( lpszData, lpnPos, lpnLen, lppszStr, nBufSize, 0, 0 );
        }

        if( ( 0 == ret ) && ( lpnStrNum ) )
        {
            *lpnStrNum = (int)uNum;
        }

        if( lpnStrNumNeeded )
        {
            *lpnStrNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_str( const char * lpszData, int * lpnPos, int * lpnLen, char * lpszStr, int nBufSize, int * lpnStrLen, int * lpnStrLenNeeded )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        const char * lpszBuf = ( const char * )lpuszBuf;
        int nLen = *lpnLen;
        int nPos = *lpnPos;
        int nStrLen = 0;

        if( 0 == ret )
        {
            nStrLen = ( lpuszBuf[nPos] << 8 ) | lpuszBuf[nPos+1];
            if( ( nStrLen + 2 > nLen ) || ( nStrLen + 1 > nBufSize ) )
            {
                ret = 1;
            }
            else
            {
                nLen -= 2;
                nPos += 2;
            }
        }

        if( ( 0 == ret ) && lpszStr )
        {
            mgr::container()->crt()->memcpy( lpszStr, lpszBuf + nPos, nStrLen );
            lpszStr[nStrLen] = 0;
            nLen -= nStrLen;
            nPos += nStrLen;
        }

        if( ( 0 == ret ) && lpnStrLen )
        {
            *lpnStrLen = nStrLen;
        }

        if( ( 0 == ret ) && lpnStrLenNeeded )
        {
            *lpnStrLenNeeded = nStrLen + 1;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_str_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, int nBufSize, const char * lppszStr, int nStrNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nStrNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nStrNum ); ++i )
        {
            lppszStr += i * nBufSize;
            ret = pack_str( lpszData, nPos, lpnLen, lpnLenLeft, lppszStr );
        }

        return ret;
    }

    int serial_impl::pack_str( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, const char * lpszStr )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        char * lpszBuf = ( char * )lpuszBuf;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;
        int nStrLen = 0;

        if( 0 == ret )
        {
            nStrLen = mgr::container()->crt()->strlen( lpszStr );
            if( nStrLen + 2 > nLenLeft )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos+0] = ( nStrLen >> 8 ) & 0xff;
            lpuszBuf[nPos+1] = nStrLen & 0xff;
            nLenLeft -= 2;
            nPos += 2;
        }

        if( 0 == ret )
        {
            mgr::container()->crt()->memcpy( lpszBuf + nPos, lpszStr, nStrLen );
            nLenLeft -= nStrLen;
            nPos += nStrLen;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_mem_array( const char * lpszData, int * lpnPos, int * lpnLen, int nBufSize, char * lppszMem, int * lpnMemLen, int nMemNum, int * lpnMemNum, int * lpnMemNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nMemNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            lppszMem += i * nBufSize;
            ret = un_pack_mem( lpszData, lpnPos, lpnLen, lppszMem, nBufSize, &lpnMemLen[i], 0 );
        }

        if( ( 0 == ret ) && ( lpnMemNum ) )
        {
            *lpnMemNum = (int)uNum;
        }

        if( lpnMemNumNeeded )
        {
            *lpnMemNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_mem( const char * lpszData, int * lpnPos, int * lpnLen, char * lpszMem, int nBufSize, int * lpnMemLen, int * lpnMemLenNeeded )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        const char * lpszBuf = ( const char * )lpuszBuf;
        int nLen = *lpnLen;
        int nPos = *lpnPos;
        int nMemLen = 0;

        if( 0 == ret )
        {
            nMemLen = ( lpuszBuf[nPos] << 8 ) | lpuszBuf[nPos+1];
            if( ( nMemLen > nLen ) || ( nMemLen > nBufSize ) )
            {
                ret = 1;
            }
            else
            {
                nLen -= 2;
                nPos += 2;
            }
        }

        if( ( 0 == ret ) && lpszMem )
        {
            mgr::container()->crt()->memcpy( lpszMem, lpszBuf + nPos, nMemLen );
            nLen -= nMemLen;
            nPos += nMemLen;
        }

        if( ( 0 == ret ) && lpnMemLen )
        {
            *lpnMemLen = nMemLen;
        }

        if( ( 0 == ret ) && lpnMemLenNeeded )
        {
            *lpnMemLenNeeded = nMemLen;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_mem_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, int nBufSize, const char * lppszMem, int * lpnMemLen, int nMemNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nMemNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nMemNum ); ++i )
        {
            lppszMem += i * nBufSize;
            ret = pack_mem( lpszData, nPos, lpnLen, lpnLenLeft, lppszMem, lpnMemLen[i] );
        }

        return ret;
    }

    int serial_impl::pack_mem( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, const char * lpszMem, int nMemLen )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        char * lpszBuf = ( char * )lpuszBuf;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;
        
        if( ( 0 == ret ) && ( nMemLen + 2 > nLenLeft ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos+0] = ( nMemLen >> 8 ) & 0xff;
            lpuszBuf[nPos+1] = nMemLen & 0xff;
            nLenLeft -= 2;
            nPos += 2;
        }

        if( 0 == ret )
        {
            mgr::container()->crt()->memcpy( lpszBuf + nPos, lpszMem, nMemLen );
            nLenLeft -= nMemLen;
            nPos += nMemLen;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_int8_array( const char * lpszData, int * lpnPos, int * lpnLen, uint8_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int8( lpszData, lpnPos, lpnLen, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = ( int )uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int8( const char * lpszData, int * lpnPos, int * lpnLen, uint8_t * lpuData )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        int nLen = *lpnLen;
        int nPos = *lpnPos;

        if( ( 0 == ret ) && ( nLen < 1 ) )
        {
            ret = 1;
        }

        if( ( 0 == ret ) && lpuData )
        {
            *lpuData = lpuszBuf[nPos];
            nLen -= 1;
            nPos += 1;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_int8_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint8_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int8( lpszData, nPos, lpnLen, lpnLenLeft, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int8( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint8_t uData )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;

        if( ( 0 == ret ) && ( 1 > nLenLeft ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos] = uData & 0xff;
            nLenLeft -= 1;
            nPos += 1;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_int16_array( const char * lpszData, int * lpnPos, int * lpnLen, uint16_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int16( const char * lpszData, int * lpnPos, int * lpnLen, uint16_t * lpuData )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        int nLen = *lpnLen;
        int nPos = *lpnPos;

        if( ( 0 == ret ) && ( nLen < 2 ) )
        {
            ret = 1;
        }

        if( ( 0 == ret ) && lpuData )
        {
            *lpuData = ( lpuszBuf[nPos] << 8 ) | lpuszBuf[nPos+1];
            nLen -= 2;
            nPos += 2;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_int16_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint16_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int16( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint16_t uData )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;

        if( ( 0 == ret ) && ( 2 > nLenLeft ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos+0] = ( uData >> 8 ) & 0xff;
            lpuszBuf[nPos+1] = uData & 0xff;
            nLenLeft -= 2;
            nPos += 2;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_int32_array( const char * lpszData, int * lpnPos, int * lpnLen, uint32_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int32( lpszData, lpnPos, lpnLen, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int32( const char * lpszData, int * lpnPos, int * lpnLen, uint32_t * lpuData )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        int nLen = *lpnLen;
        int nPos = *lpnPos;

        if( ( 0 == ret ) && ( nLen < 4 ) )
        {
            ret = 1;
        }

        if( ( 0 == ret ) && lpuData )
        {
            *lpuData = ( lpuszBuf[nPos] << 24 ) | ( lpuszBuf[nPos+1] << 16 ) | ( lpuszBuf[nPos+2] << 8 ) | lpuszBuf[nPos+3];
            nLen -= 4;
            nPos += 4;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_int32_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint32_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int32( lpszData, nPos, lpnLen, lpnLenLeft, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int32( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint32_t uData )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;

        if( ( 0 == ret ) && ( 4 > nLenLeft ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos+0] = ( uData >> 24 ) & 0xff;
            lpuszBuf[nPos+1] = ( uData >> 16 ) & 0xff;
            lpuszBuf[nPos+2] = ( uData >> 8 ) & 0xff;
            lpuszBuf[nPos+3] = uData & 0xff;
            nLenLeft -= 4;
            nPos += 4;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_int64_array( const char * lpszData, int * lpnPos, int * lpnLen, uint64_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int64( lpszData, lpnPos, lpnLen, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int64( const char * lpszData, int * lpnPos, int * lpnLen, uint64_t * lpuData )
    {
        int ret = 0;

        const unsigned char * lpuszBuf = ( const unsigned char * )lpszData;
        int nLen = *lpnLen;
        int nPos = *lpnPos;

        if( ( 0 == ret ) && ( nLen < 8 ) )
        {
            ret = 1;
        }

        if( ( 0 == ret ) && lpuData )
        {
            uint64_t uH = 0, uL = 0;
            uH = ( lpuszBuf[nPos] << 24 ) | ( lpuszBuf[nPos+1] << 16 ) | ( lpuszBuf[nPos+2] << 8 ) | lpuszBuf[nPos+3];
            nLen -= 4;
            nPos += 4;
            uL = ( lpuszBuf[nPos] << 24 ) | ( lpuszBuf[nPos+1] << 16 ) | ( lpuszBuf[nPos+2] << 8 ) | lpuszBuf[nPos+3];
            nLen -= 4;
            nPos += 4;
            *lpuData = ( uH << 32 ) | uL;
        }

        if( 0 == ret )
        {
            *lpnPos = nPos;
            *lpnLen = nLen;
        }

        return ret;
    }

    int serial_impl::pack_int64_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint64_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int64( lpszData, nPos, lpnLen, lpnLenLeft, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int64( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, uint64_t uData )
    {
        int ret = 0;

        unsigned char * lpuszBuf = ( unsigned char * )lpszData;
        int & nLenLeft = *lpnLenLeft;
        int nBasePos = nPos;
        nPos += *lpnLen;

        if( ( 0 == ret ) && ( 8 > nLenLeft ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            lpuszBuf[nPos+0] = ( uData >> 56 ) & 0xff;
            lpuszBuf[nPos+1] = ( uData >> 48 ) & 0xff;
            lpuszBuf[nPos+2] = ( uData >> 40 ) & 0xff;
            lpuszBuf[nPos+3] = ( uData >> 32 ) & 0xff;
            lpuszBuf[nPos+4] = ( uData >> 24 ) & 0xff;
            lpuszBuf[nPos+5] = ( uData >> 16 ) & 0xff;
            lpuszBuf[nPos+6] = ( uData >> 8 ) & 0xff;
            lpuszBuf[nPos+7] = uData & 0xff;
            nLenLeft -= 8;
            nPos += 8;
        }

        if( 0 == ret )
        {
            *lpnLen = nPos - nBasePos;
        }

        return ret;
    }

    int serial_impl::un_pack_float_array( const char * lpszData, int * lpnPos, int * lpnLen, float * lpfData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_float( lpszData, lpnPos, lpnLen, &lpfData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

	int serial_impl::un_pack_float( const char * lpszData, int * lpnPos, int * lpnLen, float * lpfData )
	{
		int ret = 0;

		if( 0 == ret )
		{
			int nLenNeeded = 0;
			int nLen = 0;
			ret = un_pack_mem( lpszData, lpnPos, lpnLen, (char *)lpfData, sizeof( float ), &nLen, &nLenNeeded );
		}

		return ret;
	}

    int serial_impl::pack_float_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, float * lpfData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_float( lpszData, nPos, lpnLen, lpnLenLeft, lpfData[i] );
        }

        return ret;
    }

	int serial_impl::pack_float( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, float fData )
	{
		int ret = 0;

		if( 0 == ret )
		{
			ret = pack_mem( lpszData, nPos, lpnLen, lpnLenLeft, (const char *)&fData, sizeof( float ) );
		}

		return ret;
	}

    int serial_impl::un_pack_double_array( const char * lpszData, int * lpnPos, int * lpnLen, double * lpfData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, lpnPos, lpnLen, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_double( lpszData, lpnPos, lpnLen, &lpfData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

	int serial_impl::un_pack_double( const char * lpszData, int * lpnPos, int * lpnLen, double * lpdData )
	{
		int ret = 0;

		if( 0 == ret )
		{
			int nLenNeeded = 0;
			int nLen = 0;
			ret = un_pack_mem( lpszData, lpnPos, lpnLen, (char *)lpdData, sizeof( double ), &nLen, &nLenNeeded );
		}

		return ret;
	}

    int serial_impl::pack_double_array( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, double * lpfData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, lpnLen, lpnLenLeft, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_double( lpszData, nPos, lpnLen, lpnLenLeft, lpfData[i] );
        }

        return ret;
    }

	int serial_impl::pack_double( char * lpszData, int nPos, int * lpnLen, int * lpnLenLeft, double dData )
	{
		int ret = 0;

		if( 0 == ret )
		{
			ret = pack_mem( lpszData, nPos, lpnLen, lpnLenLeft, (const char *)&dData, sizeof( double ) );
		}

		return ret;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // xos_box::i_buf *
    // 

    int serial_impl::un_pack_str_array( xos_box::i_buf * pBuf, int nBufSize, char * lppszStr, int nStrNum, int * lpnStrNum, int * lpnStrNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nStrNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            lppszStr += i * nBufSize;
            ret = un_pack_str( pBuf, lppszStr, nBufSize, 0, 0 );
        }

        if( ( 0 == ret ) && ( lpnStrNum ) )
        {
            *lpnStrNum = (int)uNum;
        }

        if( lpnStrNumNeeded )
        {
            *lpnStrNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_str( xos_box::i_buf * pBuf, char * lpszStr, int nBufSize, int * lpnStrLen, int * lpnStrLenNeeded )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_str( lpszData, &nPos, &nLen, lpszStr, nBufSize, lpnStrLen, lpnStrLenNeeded );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_str_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, int nBufSize, const char * lppszStr, int nStrNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nStrNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nStrNum ); ++i )
        {
            lppszStr += i * nBufSize;
            ret = pack_str( pBuf, lpnAbsolutePos, lppszStr );
        }

        return ret;
    }

	int serial_impl::pack_str( xos_box::i_buf * pBuf, int * lpnAbsolutePos, const char * lpszStr )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
		int nLenLeft = nSize - nAbsolutePos;
		
		if( 0 == ret )
		{
			ret = pack_str( lpszData, nPos, &nLen, &nLenLeft, lpszStr );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_str_array( xos_box::i_buf * pBuf, int nBufSize, const char * lppszStr, int nStrNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nStrNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nStrNum ); ++i )
        {
            lppszStr += i * nBufSize;
            ret = pack_str( pBuf, lppszStr );
        }

        return ret;
    }

    int serial_impl::pack_str( xos_box::i_buf * pBuf, const char * lpszStr )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_str( lpszData, nPos, &nLen, &nLenLeft, lpszStr );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_mem_array( xos_box::i_buf * pBuf, int nBufSize, char * lppszMem, int * lpnMemLen, int nMemNum, int * lpnMemNum, int * lpnMemNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nMemNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            lppszMem += i * nBufSize;
            ret = un_pack_mem( pBuf, lppszMem, nBufSize, &lpnMemLen[i], 0 );
        }

        if( ( 0 == ret ) && ( lpnMemNum ) )
        {
            *lpnMemNum = (int)uNum;
        }

        if( lpnMemNumNeeded )
        {
            *lpnMemNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_mem( xos_box::i_buf * pBuf, char * lpszMem, int nBufSize, int * lpnMemLen, int * lpnMemLenNeeded )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_mem( lpszData, &nPos, &nLen, lpszMem, nBufSize, lpnMemLen, lpnMemLenNeeded );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_mem_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, int nBufSize, const char * lppszMem, int * lpnMemLen, int nMemNum )
    {
        int ret = 0;
        
        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nMemNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nMemNum ); ++i )
        {
            lppszMem += i * nBufSize;
            ret = pack_mem( pBuf, lpnAbsolutePos, lppszMem, lpnMemLen[i] );
        }

        return ret;
    }

	int serial_impl::pack_mem( xos_box::i_buf * pBuf, int * lpnAbsolutePos, const char * lpszMem, int nMemLen )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_mem( lpszData, nPos, &nLen, &nLenLeft, lpszMem, nMemLen );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_mem_array( xos_box::i_buf * pBuf, int nBufSize, const char * lppszMem, int * lpnMemLen, int nMemNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nMemNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nMemNum ); ++i )
        {
            lppszMem += i * nBufSize;
            ret = pack_mem( pBuf, lppszMem, lpnMemLen[i] );
        }

        return ret;
    }

    int serial_impl::pack_mem( xos_box::i_buf * pBuf, const char * lpszMem, int nMemLen )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_mem( lpszData, nPos, &nLen, &nLenLeft, lpszMem, nMemLen );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_int8_array( xos_box::i_buf * pBuf, uint8_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int8( pBuf, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int8( xos_box::i_buf * pBuf, uint8_t * lpuData )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_int8( lpszData, &nPos, &nLen, lpuData );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_int8_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint8_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int8( pBuf, lpnAbsolutePos, lpuData[i] );
        }

        return ret;
    }

	int serial_impl::pack_int8( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint8_t uData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_int8( lpszData, nPos, &nLen, &nLenLeft, uData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_int8_array( xos_box::i_buf * pBuf, uint8_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int8( pBuf, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int8( xos_box::i_buf * pBuf, uint8_t uData )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_int8( lpszData, nPos, &nLen, &nLenLeft, uData );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_int16_array( xos_box::i_buf * pBuf, uint16_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int16( pBuf, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int16( xos_box::i_buf * pBuf, uint16_t * lpuData )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( lpszData, &nPos, &nLen, lpuData );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_int16_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint16_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, lpuData[i] );
        }

        return ret;
    }

	int serial_impl::pack_int16( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint16_t uData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_int16( lpszData, nPos, &nLen, &nLenLeft, uData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_int16_array( xos_box::i_buf * pBuf, uint16_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int16( pBuf, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int16( xos_box::i_buf * pBuf, uint16_t uData )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_int16( lpszData, nPos, &nLen, &nLenLeft, uData );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_int32_array( xos_box::i_buf * pBuf, uint32_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int32( pBuf, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int32( xos_box::i_buf * pBuf, uint32_t * lpuData )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_int32( lpszData, &nPos, &nLen, lpuData );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_int32_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint32_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int32( pBuf, lpnAbsolutePos, lpuData[i] );
        }

        return ret;
    }

	int serial_impl::pack_int32( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint32_t uData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_int32( lpszData, nPos, &nLen, &nLenLeft, uData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_int32_array( xos_box::i_buf * pBuf, uint32_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int32( pBuf, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int32( xos_box::i_buf * pBuf, uint32_t uData )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_int32( lpszData, nPos, &nLen, &nLenLeft, uData );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_int64_array( xos_box::i_buf * pBuf, uint64_t * lpuData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_int64( pBuf, &lpuData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

    int serial_impl::un_pack_int64( xos_box::i_buf * pBuf, uint64_t * lpuData )
    {
        int ret = 0;

        const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nLen = pBuf->get_len( 0 );
        int nPos = 0;

        if( 0 == ret )
        {
            ret = un_pack_int64( lpszData, &nPos, &nLen, lpuData );
        }

        if( 0 == ret )
        {
            pBuf->set_pos( nBasePos + nPos );
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::pack_int64_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint64_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int64( pBuf, lpnAbsolutePos, lpuData[i] );
        }

        return ret;
    }

	int serial_impl::pack_int64( xos_box::i_buf * pBuf, int * lpnAbsolutePos, uint64_t uData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_int64( lpszData, nPos, &nLen, &nLenLeft, uData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_int64_array( xos_box::i_buf * pBuf, uint64_t * lpuData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_int64( pBuf, lpuData[i] );
        }

        return ret;
    }

    int serial_impl::pack_int64( xos_box::i_buf * pBuf, uint64_t uData )
    {
        int ret = 0;

        char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int nSize = pBuf->get_buf_size( 0 );
        int nBasePos = pBuf->get_pos( 0 );
        int nPos = 0;
        int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

        if( 0 == ret )
        {
            ret = pack_int64( lpszData, nPos, &nLen, &nLenLeft, uData );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLen );
        }

        return ret;
    }

    int serial_impl::un_pack_float_array( xos_box::i_buf * pBuf, float * lpfData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_float( pBuf, &lpfData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

	int serial_impl::un_pack_float( xos_box::i_buf * pBuf, float * lpfData )
	{
		int ret = 0;

		const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
		int nBasePos = pBuf->get_pos( 0 );
		int nLen = pBuf->get_len( 0 );
		int nPos = 0;

		if( 0 == ret )
		{
			ret = un_pack_float( lpszData, &nPos, &nLen, lpfData );
		}

		if( 0 == ret )
		{
			pBuf->set_pos( nBasePos + nPos );
			pBuf->set_len( nLen );
		}

		return ret;
	}

    int serial_impl::pack_float_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, float * lpfData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_float( pBuf, lpnAbsolutePos, lpfData[i] );
        }

        return ret;
    }

	int serial_impl::pack_float( xos_box::i_buf * pBuf, int * lpnAbsolutePos, float fData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_float( lpszData, nPos, &nLen, &nLenLeft, fData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_float_array( xos_box::i_buf * pBuf, float * lpfData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_float( pBuf, lpfData[i] );
        }

        return ret;
    }

	int serial_impl::pack_float( xos_box::i_buf * pBuf, float fData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		int nPos = 0;
		int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

		if( 0 == ret )
		{
			ret = pack_float( lpszData, nPos, &nLen, &nLenLeft, fData );
		}

		if( 0 == ret )
		{
			pBuf->set_len( nLen );
		}

		return ret;
	}

    int serial_impl::un_pack_double_array( xos_box::i_buf * pBuf, double * lpdData, int nNum, int * lpnNum, int * lpNumNeeded )
    {
        int ret = 0;

        uint16_t uNum = 0;

        if( 0 == ret )
        {
            ret = un_pack_int16( pBuf, &uNum );
        }

        if( ( 0 == ret ) && ( (int)uNum > nNum ) )
        {
            ret = 1;
        }

        for( uint16_t i = 0; ( 0 == ret ) && ( i < uNum ); ++i )
        {
            ret = un_pack_double( pBuf, &lpdData[i] );
        }

        if( ( 0 == ret ) && ( lpnNum ) )
        {
            *lpnNum = (int)uNum;
        }

        if( lpNumNeeded )
        {
            *lpNumNeeded = (int)uNum;
        }

        return ret;
    }

	int serial_impl::un_pack_double( xos_box::i_buf * pBuf, double * lpdData )
	{
		int ret = 0;

		const char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
		int nBasePos = pBuf->get_pos( 0 );
		int nLen = pBuf->get_len( 0 );
		int nPos = 0;

		if( 0 == ret )
		{
			ret = un_pack_double( lpszData, &nPos, &nLen, lpdData );
		}

		if( 0 == ret )
		{
			pBuf->set_pos( nBasePos + nPos );
			pBuf->set_len( nLen );
		}

		return ret;
	}

    int serial_impl::pack_double_array( xos_box::i_buf * pBuf, int * lpnAbsolutePos, double * lpdData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, lpnAbsolutePos, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_double( pBuf, lpnAbsolutePos, lpdData[i] );
        }

        return ret;
    }

	int serial_impl::pack_double( xos_box::i_buf * pBuf, int * lpnAbsolutePos, double dData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
        int & nAbsolutePos = *lpnAbsolutePos;
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		lpszData = lpszData - nBasePos + nAbsolutePos;
		int nPos = 0;
		int nLen = 0;
        int nLenLeft = nSize - nAbsolutePos;

		if( 0 == ret )
		{
			ret = pack_double( lpszData, nPos, &nLen, &nLenLeft, dData );
		}

        if( 0 == ret )
        {
            nAbsolutePos += nLen;
        }

		return ret;
	}

    int serial_impl::pack_double_array( xos_box::i_buf * pBuf, double * lpdData, int nNum )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pack_int16( pBuf, nNum );
        }

        for( int i = 0; ( 0 == ret ) && ( i < nNum ); ++i )
        {
            ret = pack_double( pBuf, lpdData[i] );
        }

        return ret;
    }

	int serial_impl::pack_double( xos_box::i_buf * pBuf, double dData )
	{
		int ret = 0;

		char * lpszData = pBuf->get_data( 0, 0, 0, 0 );
		int nSize = pBuf->get_buf_size( 0 );
		int nBasePos = pBuf->get_pos( 0 );
		int nPos = 0;
		int nLen = pBuf->get_len( 0 );
        int nLenLeft = nSize - nLen - nBasePos;

		if( 0 == ret )
		{
			ret = pack_double( lpszData, nPos, &nLen, &nLenLeft, dData );
		}

		if( 0 == ret )
		{
			pBuf->set_len( nLen );
		}

		return ret;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 

	// 
	// 根据xos_box::i_buf中的当前进度和上次的pos, len进度，检查是否可以合下一包数据。考虑需要预留包头的字节数
	//		nRet是pack执行结果，0 : 成功，非0，失败。pack_end用它判断如果处理xos_box::i_buf中的pos和len
	// 返回值定义：
	//		0 : 成功，可以继续，已经读取xos_box::i_buf中的pos和len
	//      1 : 成功，不能继续，已经读取xos_box::i_buf中的pos和len
	//     -1 : 失败，不能继续，已经回滚xos_box::i_buf中的pos和len。下次将超缓存界
	//     -2 : 失败，不能继续，已经回滚xos_box::i_buf中的pos和len。是已经越缓存界
	// 
	int serial_impl::pack_end( xos_box::i_buf * pBuf, int & nBufPos, int & nBufLen, int nRet, int nPackageHeadLen )
	{
		int ret = 0;

		if( ( 0 == ret ) && ( 0 != nRet ) )
		{
			ret = -2;
		}

		if( 0 == ret )
		{
			int buf_len = pBuf->get_pos( 0 ) + pBuf->get_len( 0 ) + nPackageHeadLen;
			if( buf_len > xos_box::i_buf::BUF_SIZE )
			{
				ret = -1;
			}
			else if( buf_len == xos_box::i_buf::BUF_SIZE )
			{
				ret = 1;
			}
		}
		
		if( ret >= 0 )
		{
			pBuf->get_pos( &nBufPos );
			pBuf->get_len( &nBufLen );
		}
		else
		{
			pBuf->set_pos( nBufPos );
			pBuf->set_len( nBufLen );
		}

		return ret;
	}

	// 
	// 只是简单的把xos_box::i_buf中的pos和len保存到nBufPos和nBufLen中
	// 
	int serial_impl::pack_begin( xos_box::i_buf * pBuf, int & nBufPos, int & nBufLen )
	{
		int ret = 0;
		pBuf->get_pos( &nBufPos );
		pBuf->get_len( &nBufLen );
		return ret;
	}

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int serial_impl::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    int serial_impl::init()
    {
        int ret = 0;
        return ret;
    }

    int serial_impl::term()
    {
        int ret = 0;
        return ret;
    }

} // xos_common
